﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ShredTheLog.Common.MVVM;
using ShredTheLog.Api;
using System.ComponentModel.Composition;
using System.Windows.Input;
using ShredTheLog.Api.DataContracts;
using ShredTheLog.Api.DataContracts.TextChat;
using ShredTheLog.Model;
using ShredTheLog.Views;
using ShredTheLog.ViewModels;
using System.Diagnostics.Contracts;
using System.Windows.Media;
using ShredTheLog.Controls;
using System.Windows.Threading;
using System.Windows;

namespace ShredTheLog.Plugins
{
    [Export(typeof(ICommandListItem))]
    [MenuCommandMetadata(Menu = Menus.User, Order = 0, Group = null)]
    [Export(typeof(IShowProfileCommand))]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public class ShowProfileCommand : DelegateCommand<IUserInfo>, IUiCommand, IShowProfileCommand
    {
        [Import]
        private IShredServices ShredServices { get; set; }

        public ShowProfileCommand()
            : base(
            user =>
            {
                var window = Application.Current.Windows.OfType<UserProfileView>().Where(i => ((UserProfileViewModel)i.DataContext).Uid == user.Uid).SingleOrDefault();
                if (window == null)
                    new UserProfileView().Show(new UserProfileViewModel(user));
                else
                    window.Activate();
            })
        {
        }

        public string Name { get { return ShredServices.GetLocalizedString("s_ViewProfile"); } }
        public ImageSource Image { get { return null; } }
    }

    [Export(typeof(ICommandListItem))]
    [MenuCommandMetadata(Menu = Menus.User, Order = 100, Group = null)]
    [Export(typeof(IRequestPrivateChatCommand))]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public class RequestPrivateChatCommand : DelegateCommand<IUserInfo>, IUiCommand, IRequestPrivateChatCommand
    {
        private readonly IShredServices _shredServices;

        [ImportingConstructor]
        public RequestPrivateChatCommand(IShredServices shredServices)
            : base(
            user =>
            {
                Contract.Requires(user != null);

                var textChat = shredServices.TextChat;
                if (textChat != null && textChat.Credentials != null && textChat.IsConnected)
                    textChat.Update(new ShredTheLog.Api.DataContracts.TextChat.RequestPrivateChatCommand(user));
            },
            user =>
            {
                if (user == null) return false;

                var textChat = shredServices.TextChat;
                var textChatUsers = shredServices.TextChatUsers;
                return textChat != null && textChat.Credentials != null && textChat.IsConnected && textChatUsers != null && textChatUsers.Any(i => i.Uid == user.Uid);
            })
        {
            Contract.Requires(shredServices != null);

            _shredServices = shredServices;
        }

        public string Name { get { return _shredServices.GetLocalizedString("s_RequestPrivateChat"); } }
        public ImageSource Image { get { return null; } }
    }

    [Export(typeof(ICommandListItem))]
    [MenuCommandMetadata(Menu = Menus.User, Order = 200, Group = null)]
    [Export(typeof(IAddContactCommand))]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public class AddContactCommand : DelegateCommand<IUserInfo>, IAddContactCommand
    {
        [Import]
        private IShredServices ShredServices { get; set; }

        [Import]
        private IConnectionSettingsSection ConnectionSettings { get; set; }

        [Import]
        private IShowLogInDialogCommand ShowLogInDialogCommand { get; set; }

        public AddContactCommand()
        {
            _executeMethod =
                user =>
                {
                    Contract.Requires(user != null);

                    if (ShowLogInDialogCommand.Credentials != null)
                        ConnectionSettings.GetClient().AddContact(ShowLogInDialogCommand.Credentials, user).ObserveOn(ShredServices.Dispatcher).Subscribe(
                            response =>
                            {
                                try
                                {
                                    if (response.Kind == ContactListResponseKind.ContactAdded)
                                    {
                                        if (Completed != null)
                                            Completed(this, EventArgs.Empty);
                                        ShredServices.ShowMessage(() => ShredServices.GetLocalizedString("s_ContactAdded"));
                                    }
                                    else
                                    {
                                        ShredServices.ShowMessage(() => ShredServices.GetLocalizedString("s_FailedToAddContact"));
                                    }
                                }
                                catch (Exception ex)
                                {
                                    ShredServices.ShowError(ex);
                                }
                            },
                            ShredServices.ShowError);
                };
            _canExecuteMethod =
                user =>
                {
                    if (user == null) return false;

                    return ShowLogInDialogCommand.Credentials != null && ShredServices.Contacts != null && !ShredServices.Contacts.Any(i => i.Uid == user.Uid);
                };
        }

        public string Name { get { return ShredServices.GetLocalizedString("s_AddContact"); } }
        public ImageSource Image { get { return null; } }

        public event EventHandler Completed;
    }

    [Export(typeof(ICommandListItem))]
    [MenuCommandMetadata(Menu = Menus.User, Order = 300, Group = null)]
    [Export(typeof(IDeleteContactCommand))]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public class DeleteContactCommand : DelegateCommand<IUserInfo>, IDeleteContactCommand
    {
        [Import]
        private IShredServices ShredServices { get; set; }

        [Import]
        private IConnectionSettingsSection ConnectionSettings { get; set; }

        [Import]
        private IShowLogInDialogCommand ShowLogInDialogCommand { get; set; }

        public DeleteContactCommand()
        {
            _executeMethod =
                user =>
                {
                    Contract.Requires(user != null);

                    if (ShowLogInDialogCommand.Credentials != null)
                    {
                        Action<Exception> onError =
                            ex =>
                            {
                                ShredServices.ShowError(ex);
                            };

                        ConnectionSettings.GetClient().DeleteContact(ShowLogInDialogCommand.Credentials, user).ObserveOn(ShredServices.Dispatcher).Subscribe(
                            response =>
                            {
                                try
                                {
                                    if (response.Kind == ContactListResponseKind.ContactDeleted)
                                    {
                                        if (Completed != null)
                                            Completed(this, EventArgs.Empty);
                                        ShredServices.ShowMessage(() => ShredServices.GetLocalizedString("s_ContactDeleted"));
                                    }
                                    else
                                    {
                                        ShredServices.ShowMessage(() => ShredServices.GetLocalizedString("s_FailedToDeleteContact"));
                                    }
                                }
                                catch (Exception ex)
                                {
                                    onError(ex);
                                }
                            },
                            onError);
                    }
                };
            _canExecuteMethod =
                user =>
                {
                    if (user == null) return false;

                    return ShowLogInDialogCommand.Credentials != null && ShredServices.Contacts != null && ShredServices.Contacts.Any(i => i.Uid == user.Uid);
                };
        }

        public string Name { get { return ShredServices.GetLocalizedString("s_DeleteContact"); } }
        public ImageSource Image { get { return null; } }

        public event EventHandler Completed;
    }
}
